/*
 * Copyright 2010-2011, David George, Licensed under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.magneato.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.magneato.utils.parsers.FacetParser;
import org.xml.sax.SAXException;

/**
 * Every Magneato page has two templates. An Xforms format editTemplate and a
 * display template used for viewing the page. When a new page is created these
 * templates must be specified from the available set of templates. The
 * templates are found in the WEB-INF/template directory. The list of templates
 * can be narrowed by specifying an existing template, then only child templates
 * of this template will be available.
 * 
 * A template has the following characteristics:
 * <ul>
 * <li>name
 * <li>modified date - last time template was modified
 * <li>description - text description
 * <li>children - Valid templates for related pages
 * <li>display - display template(s)
 * <li>facets - a list of facet names for this template, used by navigation
 * </ul>
 * 
 * Children controls what templates children of the current page can use. They
 * can be specified by name. We can also specify: * - all templates
 * 
 * @author David George
 * 
 * @see http://www.w3.org/TR/xforms11/
 */
public class Template {
	private String name;
	private String description;
	private String children = "";
	private String displays;
	private String csum;
	private List<String> facets;
	private long lastModified;
	private final static String CHILDREN = "children:";
	private final static String DESCRIPTION = "description:";
	private final static String DISPLAY = "display:";

	/**
	 * @param name
	 *            - template name, format is: "x.<name>.vm"
	 */
	public Template(String name) {

		this.name = name;
		// display template defaults to a same named template in the same
		// directory
		displays = name;
	}

	/**
	 * Parses an xforms template file. The file has the following format <br/>
	 * <br/>
	 * <!-- description: Description of template<br/>
	 * children: permitted children of this template, optional, if no children
	 * this is a leaf<br/>
	 * display: display template, optional, if not given display template is
	 * same name as edit template --><br/>
	 * XForm document
	 * 
	 * @param templateFile
	 *            - template file
	 * 
	 * @throws IOException
	 *             , NoSuchAlgorithmException
	 * @throws SAXException
	 * @throws ParserConfigurationException
	 */
	void parseTemplateFile(File templateFile) throws IOException,
			NoSuchAlgorithmException, ParserConfigurationException,
			SAXException {
		lastModified = templateFile.lastModified();

		FileReader fileReader = null;
		BufferedReader reader = null;
		try {
			fileReader = new FileReader(templateFile);
			reader = new BufferedReader(fileReader);

			MessageDigest md5 = MessageDigest.getInstance("MD5");

			/*
			 * First
			 */
			boolean inComment = false;
			String line;
			while ((line = reader.readLine()) != null) {
				if (inComment) {
					int index;
					if ((index = line.indexOf(CHILDREN)) != -1) {
						children = line.substring(index + CHILDREN.length())
								.trim();
					} else if ((index = line.indexOf(DESCRIPTION)) != -1) {
						description = line.substring(
								index + DESCRIPTION.length()).trim();
					} else if ((index = line.indexOf(DISPLAY)) != -1) {
						displays = line.substring(index + DISPLAY.length())
								.trim();
					} else if (line.indexOf("-->") != -1) {
						break;
					}
				} else if (line.indexOf("<!--") != -1) {
					inComment = true;
				}

			}// while

			// csum rest of file
			while ((line = reader.readLine()) != null) {
				md5.update(line.getBytes());
			}
			csum = new BigInteger(1, md5.digest()).toString(16);
		} finally {
			if (fileReader != null) {
				fileReader.close();
			}
			if (reader != null) {
				reader.close();
			}
		}
		
		// now get the facets
		SAXParserFactory factory = SAXParserFactory.newInstance();
		SAXParser saxParser = factory.newSAXParser();
		FacetParser facetParser = new FacetParser();
		saxParser.parse(templateFile, facetParser);
		facets = facetParser.getFacetList();
	}

	public String getCsum() {
		return csum;
	}

	public String getName() {
		return name;
	}

	public String getDescription() {
		return description;
	}

	public String getChildren() {
		return children;
	}

	public String getDisplay() {
		return displays;
	}

	public long getLastModified() {
		return lastModified;
	}

	public List<String> getFacets() {
		return facets;
	}
}